from contextlib import asynccontextmanager

import uvicorn
from fastapi import FastAPI
from fastapi.exceptions import RequestValidationError
from starlette import status
from starlette.middleware.cors import CORSMiddleware
from starlette.responses import JSONResponse

from web.dependencies import server_manager
from web import api_router

import argparse
import signal
import sys


@asynccontextmanager
async def lifespan(app: FastAPI):
    try:
        server_manager.set_all_server()
        yield
    finally:
        server_manager.stop_all_servers()


def create_application() -> FastAPI:
    application = FastAPI(lifespan=lifespan)
    application.include_router(api_router, prefix="")
    # 添加CORS中间件
    application.add_middleware(
        CORSMiddleware,
        allow_origins=["*"],  # 允许所有源，也可以指定具体的源
        allow_credentials=True,
        allow_methods=["*"],  # 允许所有方法
        allow_headers=["*"],  # 允许所有头
    )
    # 将静态资源文件夹挂载到 '/static' 路径上
    # application.mount("/", StaticFiles(directory="/home/cdy/problem/problem_backend/www/dist/", html=True))
    return application


app = create_application()


@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request, exc):
    errors = []
    for error in exc.errors():
        field = error["loc"][-1]
        msg = error.get("msg", "参数错误")
        errors.append({"field": field, "message": msg})

    return JSONResponse(
        status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
        content={"status": 422, "msg": "参数校验失败", "errors": errors},
    )


# argparse
parser = argparse.ArgumentParser(description='Process some integers.')
parser.add_argument('--port', type=int, default=8000, help='The port number.')
args = parser.parse_args()


# 通过信号来退出服务，否则会出现终端显示退出后，实际进程仍在运行
# 定义信号处理函数
def signal_handler(sig, frame):
    print("[python] [flask] Received signal to terminate the server:", sig)
    sys.exit(0)


# 注册信号处理函数
signal.signal(signal.SIGTERM, signal_handler)
signal.signal(signal.SIGINT, signal_handler)

if __name__ == "__main__":
    uvicorn.run("app:app", host="0.0.0.0", port=args.port, reload=False)
